package jee.boot.module.oauth2.service;

import jee.boot.common.basic.ServiceException;
import jee.boot.common.basic.result.MapData;
import jee.boot.common.basic.result.MessageCodeHelper;
import jee.boot.entity.auth.Account;
import jee.boot.common.properties.ProjectConfig;
import jee.boot.common.remote.RemoteEndpoint;
import jee.boot.common.utils.ImgValidateCodeUtil;
import jee.boot.common.utils.JsonMapper;
import jee.boot.common.utils.StringUtils;
import jee.boot.common.utils.VerificationCodeUtil;
import jee.boot.entity.mail.Mail;
import jee.boot.entity.sms.Sms;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;

/**
 * 验证码服务
 */
@Service
public class ValidateCodeService {
    protected final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * 验证码有效期5分钟
     */
    private Integer timeout = 5;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private AccountService accountService;
    @Autowired
    private MessageCodeHelper messageCodeHelper;
    @Autowired
    private RemoteEndpoint remoteEndpoint;
    @Autowired
    private ProjectConfig projectConfig;

    public Map<String, String> getImgCode() {
        Map<String, String> result = new HashMap<>();
        try {
            // 获取 4位数验证码
            result = ImgValidateCodeUtil.getImgCodeBaseCode(4);
            // 将验证码存入redis 中（有效时长5分钟）
            String redisKey = VerificationCodeUtil.cacheCode(result.get("imgCode"));
            result.put("pinKey", redisKey);
            result.remove("imgCode");
        } catch (Exception e) {
            logger.error(e.toString());
            throw e;
        }
        return result;
    }

    /**
     * 发送验证码(短信,邮件)
     *
     * @param account
     * @return
     */
    public Map<String, String> sendCode(Account account) {
        Map<String, String> result = new HashMap<>();
        Account login = accountService.findListForLogin(account);
        if (login == null) {
            throw new ServiceException(1117);
        }
        // 生成随机验证码
        String code = VerificationCodeUtil.getVerificationNum(6);
        boolean sendFlag = false;
        // send sms code
        if (StringUtils.isNotBlank(login.getPhone())) {
            // if send success ,set sendFlag=true
            Sms sms = createSms(login, code);
            sms.setAsyn(false);//同步发送
            remoteEndpoint.executePost(projectConfig.getOpenMessageServer(), "/sms/send", sms, Sms.class);
            if (StringUtils.equals("Y", sms.getSendStatus())) {
                sendFlag = true;
            }
        }
        // if not success to send sms code ,retry to send mail code
        if (!sendFlag) {
            Mail mail = createMail(login, code);
            mail.setAsyn(false);//同步发送
            remoteEndpoint.executePost(projectConfig.getOpenMessageServer(), "/mail/send", mail, Mail.class);
            if (StringUtils.equals("Y", mail.getSendStatus())) {
                sendFlag = true;
            }
        }
        // send success! cache code to redis
        if (sendFlag) {
            String redisKey = VerificationCodeUtil.cacheCode(code);
            result.put("dynamicKey", redisKey);
        } else {
            throw new ServiceException(1116);
        }

        return result;
    }

    private Sms createSms(Account login, String code) {
        Sms sms=new Sms();
        sms.setPhoneNumber(login.getPhone());
        sms.setSignName(messageCodeHelper.getMessage(1437));
        sms.setTemplateCode(messageCodeHelper.getMessage(1435));
        sms.setTemplateParam(JsonMapper.toJsonString(MapData.instance().put("code",code).data()));
        return sms;
    }

    private Mail createMail(Account login, String code) {
        Map<String, Object> data = new HashMap<>();
        // 同步发送邮件
        Mail mail = new Mail();
        mail.setToMail(login.getEmail());
        mail.setTemplateName("login");
        mail.setSubject(messageCodeHelper.getMessage(1433));
        data.put("code", code);
        data.put("account", login);
        mail.setData(data);
        return mail;
    }
}
